home *** CD-ROM | disk | FTP | other *** search
/ Game Programming - All in One (3rd Edition) / game_prog_all_in_one_3rd_ed.iso / DirectX / DX8 Fix / d3dx8_0b.exe / skinnedmesh.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-14  |  16.2 KB  |  510 lines

  1. //-----------------------------------------------------------------------------
  2. // File: SkinnedMesh.cpp
  3. //
  4. // Desc: Example code showing how to use animated models with skinning.
  5. //
  6. // Copyright (c) 1999-2001 Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #define STRICT
  9. #include <tchar.h>
  10. #include <stdio.h>
  11. #include <windows.h>
  12. #include <mmsystem.h>
  13. #include <commdlg.h>
  14. #include <tchar.h>
  15. #include <d3d8.h>
  16. #include <d3dx8.h>
  17. #include "resource.h"
  18. #include "D3DApp.h"
  19. #include "D3DFont.h"
  20. #include "D3DUtil.h"
  21. #include "DXUtil.h"
  22. #include "SkinnedMesh.h"
  23.  
  24.  
  25.  
  26.  
  27. //-----------------------------------------------------------------------------
  28. // Name: WinMain()
  29. // Desc: Entry point to the program. Initializes everything, and goes into a
  30. //       message-processing loop. Idle time is used to render the scene.
  31. //-----------------------------------------------------------------------------
  32. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
  33. {
  34.     CMyD3DApplication d3dApp;
  35.  
  36.     if( FAILED( d3dApp.Create( hInst ) ) )
  37.         return 0;
  38.  
  39.     return d3dApp.Run();
  40. }
  41.  
  42.  
  43.  
  44.  
  45. //-----------------------------------------------------------------------------
  46. // Name: CMyD3DApplication()
  47. // Desc: Application constructor. Sets attributes for the app.
  48. //-----------------------------------------------------------------------------
  49. CMyD3DApplication::CMyD3DApplication()
  50. {
  51.     m_strWindowTitle    = _T("Skinned Mesh");
  52.     m_bUseDepthBuffer   = TRUE;
  53.     m_bShowCursorWhenFullscreen = TRUE;
  54.  
  55.     m_pFont  = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
  56.  
  57.     m_pmcSelectedMesh = NULL;
  58.     m_pframeSelected = NULL;
  59.     m_pdeHead = NULL;
  60.     m_pdeSelected = NULL;
  61.  
  62.     m_dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL | D3DFVF_TEX1;
  63.  
  64.     m_method = D3DNONINDEXED;
  65.  
  66.     m_pBoneMatrices = NULL;
  67.     m_maxBones = 0;
  68. }
  69.  
  70.  
  71.  
  72.  
  73. //-----------------------------------------------------------------------------
  74. // Name: ConfirmDevice()
  75. // Desc: Called during device intialization, this code checks the device
  76. //       for some minimum set of capabilities
  77. //-----------------------------------------------------------------------------
  78. HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS8* pCaps, DWORD dwBehavior,
  79.                                           D3DFORMAT Format )
  80. {
  81.     // This sample wants mixed vertex processing rather than hardware
  82.     // vertex processing so it can fallback to sw processing if the 
  83.     // device supports fewer than three matrices when skinning.
  84.     if( dwBehavior & D3DCREATE_HARDWARE_VERTEXPROCESSING )
  85.         return E_FAIL;
  86.  
  87.     return S_OK;
  88. }
  89.  
  90.  
  91.  
  92.  
  93. //-----------------------------------------------------------------------------
  94. // Name: OneTimeSceneInit()
  95. // Desc: Called during initial app startup, this function performs all the
  96. //       permanent initialization.
  97. //-----------------------------------------------------------------------------
  98. HRESULT CMyD3DApplication::OneTimeSceneInit()
  99. {
  100.     // Set cursor to indicate that user can move the object with the mouse
  101. #ifdef _WIN64
  102.     SetClassLongPtr( m_hWnd, GCLP_HCURSOR, (LONG_PTR)LoadCursor( NULL, IDC_SIZEALL ) );
  103. #else
  104.     SetClassLong( m_hWnd, GCL_HCURSOR, (LONG)LoadCursor( NULL, IDC_SIZEALL ) );
  105. #endif
  106.     return S_OK;
  107. }
  108.  
  109.  
  110.  
  111.  
  112. //-----------------------------------------------------------------------------
  113. // Name: FrameMove()
  114. // Desc: Called once per frame, the call is the entry point for animating
  115. //       the scene.
  116. //-----------------------------------------------------------------------------
  117. HRESULT CMyD3DApplication::FrameMove()
  118. {
  119.     SDrawElement *pdeCur;
  120.     SFrame *pframeCur;
  121.  
  122.     pdeCur = m_pdeHead;
  123.     while (pdeCur != NULL)
  124.     {
  125.         pdeCur->fCurTime += m_fElapsedTime * 4800;
  126.         if (pdeCur->fCurTime > 1.0e15f)
  127.             pdeCur->fCurTime = 0;
  128.  
  129.         pframeCur = pdeCur->pframeAnimHead;
  130.         while (pframeCur != NULL)
  131.         {
  132.             pframeCur->SetTime(pdeCur->fCurTime);
  133.             pframeCur = pframeCur->pframeAnimNext;
  134.         }
  135.  
  136.         pdeCur = pdeCur->pdeNext;
  137.     }
  138.     
  139.     return S_OK;
  140. }
  141.  
  142.  
  143.  
  144.  
  145. //-----------------------------------------------------------------------------
  146. // Name: Render()
  147. // Desc: Called once per frame, the call is the entry point for 3d
  148. //       rendering. This function sets up render states, clears the
  149. //       viewport, and renders the scene.
  150. //-----------------------------------------------------------------------------
  151. HRESULT CMyD3DApplication::Render()
  152. {
  153.     // Set up viewing postion from ArcBall
  154.     SDrawElement *pdeCur;
  155.     D3DXMATRIX mat;
  156.     pdeCur = m_pdeHead;
  157.     while (pdeCur != NULL)
  158.     {
  159.         pdeCur->pframeRoot->matRot = *m_ArcBall.GetRotationMatrix();
  160.         pdeCur->pframeRoot->matTrans = *m_ArcBall.GetTranslationMatrix();
  161.         pdeCur = pdeCur->pdeNext;
  162.     }
  163.     
  164.     // Clear the viewport
  165.     m_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(89,135,179), 1.0f, 0 );
  166.  
  167.     if (m_pdeHead == NULL)
  168.     {
  169.         return S_OK;
  170.     }
  171.  
  172.     // Begin the scene 
  173.     if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
  174.     {
  175.         UINT cTriangles = 0;
  176.         HRESULT hr;
  177.         SDrawElement *pdeCur;
  178.         D3DXMATRIX matD3D;
  179.         D3DXMATRIX mOut;
  180.         D3DXMATRIX mCur;
  181.         D3DXVECTOR3 vTemp;
  182.         D3DXMATRIX mObject;
  183.         D3DXMATRIX mTrans;
  184.         LPDIRECT3DDEVICE8 m_pDevice = m_pd3dDevice;
  185.  
  186.  
  187.         D3DXMatrixTranslation(&mTrans, 0, 0, -m_pdeSelected->fRadius * 2.8f);
  188.  
  189.         hr = m_pDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)&mTrans);
  190.         if(FAILED(hr))
  191.             return hr;
  192.  
  193.         pdeCur = m_pdeHead;
  194.         while (pdeCur != NULL)
  195.         {
  196.             D3DXMatrixTranslation(&mTrans, -pdeCur->vCenter.x, -pdeCur->vCenter.y, -pdeCur->vCenter.z);
  197.             D3DXMatrixIdentity(&mCur);
  198.  
  199.             hr = UpdateFrames(pdeCur->pframeRoot, mCur);
  200.             if (FAILED(hr))
  201.                 return hr;
  202.             hr = DrawFrames(pdeCur->pframeRoot, cTriangles);
  203.             if (FAILED(hr))
  204.                 return hr;
  205.  
  206.             pdeCur = pdeCur->pdeNext;
  207.         }
  208.  
  209.         // Show frame rate
  210.         m_pFont->DrawText( 2,  0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats );
  211.         m_pFont->DrawText( 2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats );
  212.  
  213.         // End the scene.
  214.         m_pd3dDevice->EndScene();
  215.     }
  216.  
  217.     return S_OK;
  218. }
  219.  
  220.  
  221.  
  222.  
  223. //-----------------------------------------------------------------------------
  224. // Name: InitDeviceObjects()
  225. // Desc: Initialize scene objects.
  226. //-----------------------------------------------------------------------------
  227. HRESULT CMyD3DApplication::InitDeviceObjects()
  228. {
  229.     HRESULT hr = S_OK;
  230.  
  231.     // Restore the fonts
  232.     m_pFont->InitDeviceObjects( m_pd3dDevice );
  233.  
  234.     DXUtil_FindMediaFile( m_szPath, _T("tiny.x") );
  235.  
  236.     LoadMeshHierarchy();
  237.  
  238.     if( m_pdeHead != NULL)
  239.         m_ArcBall.SetRadius( m_pdeHead->fRadius );
  240.     
  241.     return S_OK;
  242. }
  243.  
  244.  
  245.  
  246.  
  247. //-----------------------------------------------------------------------------
  248. // Name: RestoreDeviceObjects()
  249. // Desc: Initialize scene objects.
  250. //-----------------------------------------------------------------------------
  251. HRESULT CMyD3DApplication::RestoreDeviceObjects()
  252. {
  253.     // Restore the fonts
  254.     m_pFont->RestoreDeviceObjects();
  255.  
  256.     HRESULT hr = S_OK;
  257.     D3DLIGHT8 light;
  258.  
  259.     m_ArcBall.SetWindow( m_d3dsdBackBuffer.Width, m_d3dsdBackBuffer.Height, 2.0f );
  260.  
  261.     if (m_pdeSelected != NULL)
  262.         SetProjectionMatrix();
  263.  
  264.     m_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE, TRUE );
  265.     m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
  266.     m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, TRUE );
  267.     m_pd3dDevice->SetRenderState( D3DRS_NORMALIZENORMALS, TRUE );
  268.  
  269.     m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
  270.     m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
  271.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR  );
  272.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR  );
  273.  
  274.     m_pd3dDevice->SetRenderState( D3DRS_COLORVERTEX, FALSE );
  275.  
  276.     ZeroMemory( &light, sizeof(light) );
  277.     light.Type = D3DLIGHT_DIRECTIONAL;
  278.  
  279.     light.Diffuse.r = 1.0;
  280.     light.Diffuse.g = 1.0;
  281.     light.Diffuse.b = 1.0;
  282.     light.Specular.r = 0;
  283.     light.Specular.g = 0;
  284.     light.Specular.b = 0;
  285.     light.Ambient.r = 0.25;
  286.     light.Ambient.g = 0.25;
  287.     light.Ambient.b = 0.25;
  288.  
  289.     light.Direction = D3DXVECTOR3( 0.0f, 0.0f, -1.0f);
  290.  
  291.     hr = m_pd3dDevice->SetLight(0, &light );
  292.     if (FAILED(hr))
  293.         return E_FAIL;
  294.  
  295.     hr = m_pd3dDevice->LightEnable(0, TRUE);
  296.     if (FAILED(hr))
  297.         return E_FAIL;
  298.  
  299.     return S_OK;
  300. }
  301.  
  302.  
  303.  
  304.  
  305. //-----------------------------------------------------------------------------
  306. // Name: ReleaseDeviceDependentMeshes()
  307. // Desc: 
  308. //-----------------------------------------------------------------------------
  309. void ReleaseDeviceDependentMeshes(SFrame* pframe)
  310. {
  311.     if (pframe->pmcMesh != NULL)
  312.     {
  313.         for (SMeshContainer* pmcCurr = pframe->pmcMesh; pmcCurr != NULL; pmcCurr = pmcCurr->pmcNext)
  314.         {
  315.             if (pmcCurr->m_pSkinMesh != NULL)
  316.             {
  317.                 GXRELEASE(pmcCurr->pMesh);
  318.                 GXRELEASE(pmcCurr->pMeshSW);
  319.  
  320.                 pmcCurr->m_Method = NONE;
  321.             }
  322.         }
  323.     }
  324.  
  325.     if (pframe->pframeFirstChild != NULL)
  326.         ReleaseDeviceDependentMeshes(pframe->pframeFirstChild);
  327.  
  328.     if (pframe->pframeSibling != NULL)
  329.         ReleaseDeviceDependentMeshes(pframe->pframeSibling);
  330. }
  331.  
  332.  
  333.  
  334.  
  335. //-----------------------------------------------------------------------------
  336. // Name: InvalidateDeviceObjects()
  337. // Desc: Called when the app is exiting, or the device is being changed,
  338. //       this function deletes any device dependent objects.
  339. //-----------------------------------------------------------------------------
  340. HRESULT CMyD3DApplication::InvalidateDeviceObjects()
  341. {
  342.     m_pFont->InvalidateDeviceObjects();
  343.  
  344.  
  345.     for (SDrawElement* pdeCurr = m_pdeHead; pdeCurr != NULL; pdeCurr = pdeCurr->pdeNext)
  346.     {
  347.         ReleaseDeviceDependentMeshes(pdeCurr->pframeRoot);
  348.     }
  349.  
  350.     return S_OK;
  351. }
  352.  
  353.  
  354.  
  355.  
  356. //-----------------------------------------------------------------------------
  357. // Name: DeleteDeviceObjects()
  358. // Desc: Called when the app is exiting, or the device is being changed,
  359. //       this function deletes any device dependent objects.
  360. //-----------------------------------------------------------------------------
  361. HRESULT CMyD3DApplication::DeleteDeviceObjects()
  362. {
  363.     m_pFont->DeleteDeviceObjects();
  364.     
  365.     if( m_pdeSelected == m_pdeHead )
  366.         m_pdeSelected = NULL;
  367.  
  368.     delete m_pdeHead;
  369.     m_pdeHead = NULL;
  370.     
  371.     delete [] m_pBoneMatrices;
  372.  
  373.     return S_OK;
  374. }
  375.  
  376.  
  377.  
  378.  
  379. //-----------------------------------------------------------------------------
  380. // Name: FinalCleanup()
  381. // Desc: Called before the app exits, this function gives the app the chance
  382. //       to cleanup after itself.
  383. //-----------------------------------------------------------------------------
  384. HRESULT CMyD3DApplication::FinalCleanup()
  385. {
  386.     SAFE_DELETE( m_pFont );
  387.  
  388.     return S_OK;
  389. }
  390.  
  391.  
  392.  
  393.  
  394. //-----------------------------------------------------------------------------
  395. // Name: MsgProc()
  396. // Desc: Message proc function to handle key and menu input
  397. //-----------------------------------------------------------------------------
  398. LRESULT CMyD3DApplication::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam,
  399.                                     LPARAM lParam )
  400. {
  401.     // Pass mouse messages to the ArcBall so it can build internal matrices
  402.     m_ArcBall.HandleMouseMessages( hWnd, uMsg, wParam, lParam );
  403.  
  404.     switch( uMsg )
  405.     {
  406.     case WM_COMMAND:
  407.         if ( 0 == HIWORD(wParam) )
  408.         {
  409.             switch ( LOWORD(wParam) )
  410.             {                
  411.             case ID_FILE_OPENMESHHEIRARCHY:
  412.                 {
  413.                     OPENFILENAME ofn;
  414.                     memset( &ofn, 0, sizeof(ofn) );
  415.                     static TCHAR file[256];
  416.                     static TCHAR szFilepath[256];
  417.                     static TCHAR fileTitle[256];
  418.                     static TCHAR filter[] =
  419.                         TEXT("X files (*.x)\0*.x\0")
  420.                         TEXT("All Files (*.*)\0*.*\0");
  421.                     _tcscpy( file, TEXT(""));
  422.                     _tcscpy( fileTitle, TEXT(""));
  423.                     
  424.                     ofn.lStructSize       = sizeof(ofn);
  425.                     ofn.hwndOwner         = m_hWnd;
  426.                     ofn.hInstance         = NULL;//m_hInstance;
  427.                     ofn.lpstrFilter       = filter;
  428.                     ofn.lpstrCustomFilter = NULL;
  429.                     ofn.nMaxCustFilter    = 0L;
  430.                     ofn.nFilterIndex      = 1L;
  431.                     ofn.lpstrFile         = file;
  432.                     ofn.nMaxFile          = sizeof(file);
  433.                     ofn.lpstrFileTitle    = fileTitle;
  434.                     ofn.nMaxFileTitle     = sizeof(fileTitle);
  435.                     ofn.lpstrInitialDir   = NULL;
  436.                     ofn.nFileOffset       = 0;
  437.                     ofn.nFileExtension    = 0;
  438.                     ofn.lpstrDefExt       = TEXT("*.x");
  439.                     ofn.lCustData         = 0;
  440.                     
  441.                     ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
  442.                     if ( ! GetOpenFileName( &ofn) )
  443.                     {
  444.                         TCHAR s[40];
  445.                         DWORD dwErr = CommDlgExtendedError();
  446.                         if ( 0 != dwErr )
  447.                         {
  448.                             wsprintf( s, "GetOpenFileName failed with %x", dwErr );
  449.                             MessageBox( m_hWnd, s, "TexWin", MB_OK | MB_SYSTEMMODAL );
  450.                         }
  451.                         return 0;
  452.                     }
  453.                     lstrcpy(m_szPath, ofn.lpstrFile);
  454.                     HRESULT hr = LoadMeshHierarchy();
  455.                     if (FAILED(hr))
  456.                         MessageBox(NULL, "Could not open file or incorrect file type", "Error loading file", MB_OK);
  457.  
  458.                     return 0;
  459.                 }
  460.             case ID_OPTIONS_D3DINDEXED:
  461.                 {
  462.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DINDEXED, MF_CHECKED);
  463.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DNONINDEXED, MF_UNCHECKED);
  464.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_SOFTWARESKINNING, MF_UNCHECKED);
  465.                     m_method = D3DINDEXED;
  466.                     break;
  467.                 }
  468.             case ID_OPTIONS_D3DNONINDEXED:
  469.                 {
  470.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DINDEXED, MF_UNCHECKED);
  471.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DNONINDEXED, MF_CHECKED);
  472.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_SOFTWARESKINNING, MF_UNCHECKED);
  473.                     m_method = D3DNONINDEXED;
  474.                     break;
  475.                 }
  476.             case ID_OPTIONS_SOFTWARESKINNING:
  477.                 {
  478.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DINDEXED, MF_UNCHECKED);
  479.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_D3DNONINDEXED, MF_UNCHECKED);
  480.                     CheckMenuItem(GetMenu(hWnd), ID_OPTIONS_SOFTWARESKINNING, MF_CHECKED);
  481.                     m_method = SOFTWARE;
  482.                     break;
  483.                 }
  484.             }
  485.         }
  486.         break;
  487.     }
  488.  
  489.     return CD3DApplication::MsgProc( hWnd, uMsg, wParam, lParam );
  490. }
  491.  
  492.  
  493.  
  494.  
  495. //-----------------------------------------------------------------------------
  496. // Name: SetProjectionMatrix()
  497. // Desc: 
  498. //-----------------------------------------------------------------------------
  499. HRESULT CMyD3DApplication::SetProjectionMatrix()
  500. {
  501.     D3DXMATRIX mat;
  502.  
  503.     if (m_pdeHead == NULL)
  504.         return S_OK;
  505.  
  506.     FLOAT fAspect = m_d3dsdBackBuffer.Width / (FLOAT)m_d3dsdBackBuffer.Height;
  507.     D3DXMatrixPerspectiveFovRH(&mat, 0.25f*3.141592654f, fAspect, m_pdeSelected->fRadius / 64, m_pdeSelected->fRadius * 200);
  508.     return m_pd3dDevice->SetTransform( D3DTS_PROJECTION, (D3DMATRIX*)&mat );
  509. }
  510.